package com.leil.fileserver.service;

import com.leil.fileserver.client.MinIOClient;
import com.leil.fileserver.enumeration.ImageTypesEnum;
import com.leil.fileserver.exception.FileOptException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;


public abstract class UploadService {

    protected String[] allowSuffix = new String[]{"*"};
    ;

    protected int maxSize = 10 * 1024 * 1024;

    protected String bucketName = "default";

    @Autowired
    MinIOClient minIOClient;

    /**
     * 初始化
     */
    @PostConstruct
    private void init() {
        this.initAllowSuffix();
        this.initMaxSize();
        this.initBucketName();
    }


    /**
     * 上传
     *
     * @param file     文件名称
     * @param isRename 是否重命名
     * @return 文件相对访问路径
     * @throws FileOptException
     */
    public String Upload(MultipartFile file, boolean isRename) throws FileOptException {
        if (file.isEmpty()) {
            throw new FileOptException("上传文件为空");
        }
        this.check(file);
        String fileName = file.getOriginalFilename();
        if (isRename && fileName != null) {
            String suffix = this.getFileSuffix(file);
            if (StringUtils.isEmpty(this.getFileName())) {
                throw new FileOptException("获取的文件名称为空");
            }
            fileName = this.getFileName() + suffix;
        }
        String targetPath = StringUtils.isEmpty(this.getPath()) ? "" : this.getPath();
        String fullPath = targetPath + "/" + fileName;
        InputStream stream;
        try {
            stream = file.getInputStream();
        } catch (IOException e) {
            throw new FileOptException("获取文件流异常，上传失败");
        }
        minIOClient.makeBucket(this.bucketName);
        minIOClient.putObject(this.bucketName, fullPath, stream, file.getSize());
        return "/static/" + this.bucketName + "/" + fullPath;
    }


    public abstract void initAllowSuffix();

    public abstract void initMaxSize();

    public abstract void initBucketName();

    /**
     * 检查文件合法性
     *
     * @param file 文件
     * @throws FileOptException
     */
    public void check(MultipartFile file) throws FileOptException {
        this.checkFileSize(file);
        this.checkFileSuffix(file);
        this.checkFile(file);
    }

    /**
     * 检测文件后缀
     *
     * @param file
     */
    protected void checkFileSuffix(MultipartFile file) throws FileOptException {
        if (Arrays.stream(allowSuffix).anyMatch(s -> StringUtils.equals(s, "*"))) {
            // 如果包含*号，表示通配所有类型，跳过检测
            return;
        }
        String suffix = this.getFileSuffix(file);
        boolean bool = Arrays.stream(allowSuffix).anyMatch(s -> StringUtils.equals(suffix, s));
        if (!bool) {
            throw new FileOptException("文件格式不支持");
        }
    }

    protected String getFileSuffix(MultipartFile file) throws FileOptException {
        String originalFilename = file.getOriginalFilename();
        if (originalFilename.lastIndexOf(".") == -1) {
            if (StringUtils.equals(this.getSuffixFromContentType(file.getContentType()), "")) {
                throw new FileOptException("缺失文件后缀名称");
            } else {
                return this.getSuffixFromContentType(file.getContentType());
            }
        }
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        return suffix;
    }

    /**
     * 通过ContentType获取文件后缀
     *
     * @param contentType 内容类型
     * @return 文件后缀
     */
    protected String getSuffixFromContentType(String contentType) {
        switch (contentType) {
            case ImageTypesEnum.JPEG:
                return ".jpeg";
            case ImageTypesEnum.PNG:
                return ".png";
            case ImageTypesEnum.SVG:
                return ".svg";
        }
        return "";
    }


    /**
     * 检测文件尺寸
     *
     * @param file
     * @throws FileOptException
     */
    protected void checkFileSize(MultipartFile file) throws FileOptException {
        if (file.getSize() > maxSize) {
            throw new FileOptException("文件尺寸太大");
        }
    }

    public abstract void checkFile(MultipartFile file) throws FileOptException;

    public abstract String getFileName();

    public abstract String getPath();

    /**
     * 获取当前日期作为存储路径
     *
     * @return
     */
    protected String getDatePath() {
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String targetPath = format.format(new Date());
        return targetPath;
    }


    /**
     * 返回当前时间为文件名称
     *
     * @return 返回文件名（格式：yyyyMMdd-HHmmss）
     */
    protected String getDateName() {
        DateFormat format = new SimpleDateFormat("yyyyMMdd-HHmmss");
        String name = format.format(new Date());
        return name;
    }


}
